package com.yitao.cms.config.permission.Interceptor;


import com.skipper.base.bean.DataOutput;
import com.skipper.base.json.JSON;
import com.yitao.cms.constant.UserErrorEnum;
import com.yitao.cms.constant.UserSession;
import com.yitao.cms.utils.RedisUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * @Auther: wuwenlong
 * @Date: 2018/6/11 0011 14:33
 * @Description:
 */
public class PermissionHandlerInterceptor implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private RedisUtil redisUtil;

    //请求前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //跨域请求
        String origin = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", origin);
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Headers", "Origin,Content-Type,Accept,token,X-Requested-With");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        String loginPath = request.getRequestURI();

        HttpSession session = request.getSession();
        logger.info("访问地址：{}，{}，{}", request.getRemoteAddr(), request.getRemoteHost(), request.getRemotePort());
        logger.info("loginPath请求路径:{}", loginPath);
        logger.info("sessionId:{}", session.getId());
        //拦截器释放资源
        if ("/yitao/user/login".equals(loginPath)
                || "/yitao/swagger-resources/configuration/ui".equals(loginPath)
                || loginPath.contains("swagger")
                || "yitao/v2/api-docs".equals(loginPath)
                || "/yitao/user/getVerifyCode".equals(loginPath) // 短信验证码
                || "/yitao/user/checkoutVerifyCode".equals(loginPath) // 短信验证码验证
                || "/yitao/user/forgetPwd".equals(loginPath) // 忘记密码，找回密码
                || "/yitao/user/register".equals(loginPath) // 用户注册
                || "/yitao/user/updatePassword".equals(loginPath)//忘记密码
                || "/yitao/cms/upload/head".equals(loginPath)//获取图片头
                || "/yitao/cms/overseasLogistics/warehouse/Callback".equals(loginPath) // 接收入库状态推送
                || "/yitao/cms/overseasLogistics/transferStatus/Callback".equals(loginPath) // 接受转运状态推送-P4
                || "/yitao/cms/expressage/import".equals(loginPath) // 测试暂时放开
                || "/yitao/cms/exchangeRate/save".equals(loginPath) // 货币汇率
                || "/yitao/cms/intergenix/getExchangeRate".equals(loginPath) // 供应链获取汇率
                || "/yitao/cms/intergenix/getLogisticDetail".equals(loginPath) // 供应链获取物流信息
                || "/yitao/cms/intergenix/saveLogistic".equals(loginPath) // 供应链新增爬取物流信息单号
                || "/yitao/cms/intergenix/closeLogisticTask".equals(loginPath) // 供应链取消爬取物流信息单号
                ) {
            return true;
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter out;
        //验证是否登录
        logger.info("session.getAttribute(user_session)获取登录信息{}", session.getAttribute(UserSession.SESSION_OPERATION_USER));
        if (session.getAttribute(UserSession.SESSION_OPERATION_USER) == null) {
            try {
                DataOutput dataOutput = new DataOutput(UserErrorEnum.NULL_LOGIN.getCode(), UserErrorEnum.NULL_LOGIN.getDesc());
                out = response.getWriter();
                out.append(JSON.toJSONString(dataOutput));
                return false;
            } catch (IOException e) {
                logger.error("获取登录信息失败：", e.getMessage());
                response.sendError(500);
                return false;
            }
        }

        //验证权限
        if (this.hasPermission(request, handler)) {
            return true;
        } else {
            //没有权限
            DataOutput dataOutput = new DataOutput(UserErrorEnum.USER_ASSECC_PERMISSION.getCode(), UserErrorEnum.USER_ASSECC_PERMISSION.getDesc());
            out = response.getWriter();
            out.append(JSON.toJSONString(dataOutput));
            return false;
        }

    }

    //请求结束执行
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }
    //视图渲染完成后才执行
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }

    /**
     * 是否有权限
     */
    private boolean hasPermission(HttpServletRequest request, Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //获取方法上的注释
            RequiredPermission requiredPermission = handlerMethod.getMethod().getAnnotation(RequiredPermission.class);
            //如果方法上的注解为空，则获取类的注解
            if (requiredPermission == null) {
                requiredPermission = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequiredPermission.class);
            }
            //如果标记了注解，则判断权限
            if (requiredPermission != null && StringUtils.isNotBlank(requiredPermission.value())) {
                //获取用户权限信息并判断是否有权限
                HttpSession session = request.getSession();
                String userId = (String) session.getAttribute(UserSession.SESSION_OPERATION_USER);
                List<String> perms = (List<String>) redisUtil.getObject(userId);
                if (CollectionUtils.isEmpty(perms)) {
                    return false;
                }
                return perms.contains(requiredPermission.value());
            }
        }
        return true;
    }
}
